using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Box2D.XNA;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Devices.Sensors;

namespace Elementum
{
    public class SpotLight : RenderObject,ChangeStateable
    {
        World _world;
        RayCast _rayCast;
        List<RayShot> _ratList;
        //Accelerometer _acceleMeter;
        Vector2 _position;
        float Vy = 0;
        float tempCount;
        Vector3 _accelReading = new Vector3();
        private RenderTarget2D _scene;
        bool _isLight;
        bool _iniLight;
        //static List<SpotLight> _spotLightList = new List<SpotLight>();
        public bool IsLight
        {
            get { return _isLight; }
            set { _isLight = value;
            _iniLight = value;
            }
        }

        public void ChangeState(bool active)
        {
            ChangeState();
        }

        public  void ChangeState()
        {
            bool temp = _isLight;
            IsLight = !IsLight;
            _iniLight = temp;
        }

        public SpotLight(Game game, World world)
            : base(game)
        {
            this._world = world;
            _rayCast = new RayCast(_world);
            Initialize();
        }

        public override void Restart() {
            IsLight = _iniLight;
        }

        public override void Initialize()
        {
            base.Initialize();
            _scene = ResourceManager._scene;
            IsLight = true;
            BaseAngle = 0;
            ScanRange = 70;
            Range = 220;
            _ratList = _rayCast.RayList;
            //_scene = new RenderTarget2D(GraphicsDevice, (int)(Range * 2), (int)(Range * 2));
            GameClass._acceleMeter.ReadingChanged += GSensorChanged;
            try
            {
                GameClass._acceleMeter.Start();
            }
            catch (AccelerometerFailedException e) { }
            catch (UnauthorizedAccessException e) { }
            //_acceleMeter.
        }

        public float ScanRange
        {
            get { return _rayCast.ScanRange; }
            set { _rayCast.ScanRange = value; }
        }

        void GSensorChanged(object sender, AccelerometerReadingEventArgs e)
        {
            _accelReading.X = (float)e.X;
            _accelReading.Y = -(float)e.Y;
            _accelReading.Z = (float)e.Z;
        }

        public override Vector2 Position
        {
            get { return _position; }
            set
            {
                _position = value;
                Vector2 v = new Vector2(value.X, GraphicsDevice.Viewport.Height - value.Y);
                _rayCast.Position = v;
            }
        }

        public float Range
        {
            set
            {
                _rayCast.Range = value;
                //if (_scene != null)
                //    _scene.Dispose();
                //_scene = new RenderTarget2D(GraphicsDevice, (int) value* 2, (int)value * 2);
                
            }
            get
            {
                return _rayCast.Range;
            }
        }

        public override void Update(int delta)
        {
            base.Update(delta);
            UpdateAngle();
            if (InView && IsLight)
            CalculateShape();
        }

        private void CalculateShape()
        {
            _rayCast.UpDate();
            GraphicsDevice.SetRenderTarget(_scene);
            Vector2 basePosition = new Vector2(_scene.Width / 2, _scene.Height / 2);
            GraphicsDevice.Clear(Color.Transparent);
            primitiveBatch.Viewport = basePosition * 2;
            primitiveBatch.Begin(PrimitiveType.TriangleList);
            for (int i = 0; i < _ratList.Count(); i++)
            {
                primitiveBatch.AddVertex(basePosition, new Color(255, 255, 225, 128));
                float _angle1 = _ratList[i].Angle;
                float _angle2 = _ratList[i].Angle + (PI / 180f);

                float length = _ratList[i].Length;
                primitiveBatch.AddVertex(basePosition + new Vector2((float)Math.Cos(_angle2), -(float)Math.Sin(_angle2)) * length, new Color(255, 255, 248, 128));
                primitiveBatch.AddVertex(basePosition + new Vector2((float)Math.Cos(_angle1), -(float)Math.Sin(_angle1)) * length, new Color(255, 255, 248, 128));
            }
            primitiveBatch.End();
            GraphicsDevice.SetRenderTarget(null);
        }

        private void UpdateAngle()
        {
            if (_accelReading.Y > 0.2)
            {
                if (BaseAngle > -60)
                {
                    Vy = 0;
                }
                else
                {
                    Vy = _accelReading.Y * 3;
                }
                tempCount = 1;
            }
            else if (_accelReading.Y < -0.2)
            {
                if (BaseAngle < -120)
                {
                    Vy = 0;
                }
                else
                {
                    Vy = _accelReading.Y * 3;
                }
                tempCount = 1;
            }
            else
            {
                if (BaseAngle > -90)
                {
                    if (BaseAngle > -60 - 5 * tempCount)
                    {
                        Vy = -0.05f;
                    }
                    else
                    {
                        tempCount += 0.005f;
                        Vy -= 0.01f * (float)(1 / tempCount);
                    }
                }
                else
                {
                    if (BaseAngle < -120 + 5 * tempCount)
                    {
                        Vy = 0.05f;
                    }
                    else
                    {
                        tempCount += 0.005f;
                        Vy += 0.01f * (float)(1 / tempCount);
                    }
                }
            }

            BaseAngle += Vy;
        }

        public float BaseAngle
        {
            get
            {
                return _rayCast.BaseAngle;
            }
            set
            {
                _rayCast.BaseAngle = value;
            }
        }

        Vector2 _drawPos;
        //bool _isInView;

        public override bool InView
        {
            get
            {
                if (_transform == null)
                    throw new Exception("null transform matrix!");
                Vector2 pos = Vector2.Transform(Position, _transform);
                pos.Y += Range / 2;
                Vector2 viewBund = new Vector2(_scene.Width, _scene.Height);
                viewBund /= 2.45f;
                viewBund = Vector2.Zero;
                if (pos.X > -viewBund.X && pos.X < 800 + viewBund.Y
                    && pos.Y > -viewBund.Y && pos.Y < 480 + viewBund.Y)
                    return true;
                return false;
            }
        }

        public override void Dispose()
        {
            base.Dispose();
            //if (_scene != null)
            //    _scene.Dispose();
            primitiveBatch.Dispose();
            //_acceleMeter.Dispose();
        }

        public override void OnDraw(SpriteBatch spriteBatch, Matrix transform)
        {
            base.OnDraw(spriteBatch, transform);
            Vector2 position = Position;            
            Vector2 halfSize = new Vector2(_scene.Width/2,_scene.Height/2);//512,512
            this._drawPos = Position;//center
            if (InView && IsLight)
            {
            spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, null, null, null, null, transform);   
            spriteBatch.Draw(_scene, position-halfSize, new Color(255,255,233,106));
            spriteBatch.End();
            }
        }

    }
}
